#include <Windows.h>
#include <gdiplus.h>

#pragma comment(lib,"gdiplus")

using namespace Gdiplus;

struct InitGdip
{
	InitGdip()
	{
		GdiplusStartupInput gsi;
		ULONG_PTR token;

		GdiplusStartup(&token, &gsi, NULL);
	}
} init;

const int ALPHA = 128;

const int XSCREEN = GetSystemMetrics(SM_CXSCREEN);
const int YSCREEN = GetSystemMetrics(SM_CYSCREEN);
BLENDFUNCTION bf = { 0,0,MAXBYTE,AC_SRC_ALPHA, };
//SIZE size = { XSCREEN,YSCREEN };
double xwindow = 300;
double ywindow = 300;
int leftwindow = (XSCREEN - xwindow) / 2;
int topwindow = (YSCREEN - ywindow) / 2;

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void frame();

Image * image = 0;
HDC hdc;
HDC memDC;
HWND mhwnd;
Graphics * graphics;

SolidBrush PALE{ 0xffb0b0b0 };
SolidBrush GRAY{ 0xffa0a0a0 };

int state = 0;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdLine, int ncmdShow)
{
	WNDCLASSEX wc = { 0 };
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
	wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
	wc.hInstance = hInstance;
	wc.lpszClassName = L"Window";
	wc.lpfnWndProc = WndProc;

	RegisterClassEx(&wc);

	mhwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_ACCEPTFILES, L"Window", L"BreakWindow", WS_POPUP, leftwindow, topwindow, xwindow, ywindow, NULL, NULL, hInstance, NULL);

	UpdateWindow(mhwnd);
	ShowWindow(mhwnd, ncmdShow);

	hdc = GetDC(mhwnd);
	memDC = CreateCompatibleDC(hdc);
	BITMAPINFO bmi = { sizeof(bmi),XSCREEN,YSCREEN,1,32, };
	HBITMAP bmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, nullptr, nullptr, 0);
	SelectObject(memDC, bmp);
	DeleteObject(bmp);
	graphics = new Graphics(memDC);
	graphics->Clear(0xffffffff);
	//graphics->SetSmoothingMode(SmoothingMode::SmoothingModeAntiAlias);

	MSG msg;
	do
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			frame();
		}
	} while (msg.message != WM_QUIT);

	ReleaseDC(mhwnd, hdc);
	DeleteDC(memDC);
	delete graphics;

	return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static RECT origin = { 0 };
	static bool canmove = false;

	switch (message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_DROPFILES:
	{
		HDROP drop = (HDROP)(wParam);
		TCHAR file[MAX_PATH] = { 0 };

		DragQueryFile(drop, 0, file, 100);

		if (image)
		{
			delete image;
		}
		else
		{
			state = 2;
		}
		image = new Image(file);
		xwindow = min(image->GetWidth(), XSCREEN);
		ywindow = min(image->GetHeight(),YSCREEN);
	}
	case WM_MOUSEWHEEL:
		int zDelta;
		zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
		if (state == 2)
		{
			if (zDelta > 0)
			{
				ywindow -= 5.0;
				if (ywindow <= 100)
				{
					ywindow = 100;
				}
				else
				{
					xwindow -= 5.0 * xwindow / ywindow;
				}
			}
			else if (zDelta < 0)
			{
				ywindow += 5.0;
				xwindow += 5.0 * xwindow / ywindow;
			}
		}
		break;
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
	}

	return 0;
}

void frame()
{
	static bool lastkey[256] = { 0 };
	bool curkey[256];
	static POINT lastpt = { 0 };
	static RECT origin = { 0 };
	static bool canmove = false;
	POINT curpt;

	HWND topmost = GetForegroundWindow();
	if (topmost != mhwnd)
	{
		SetWindowPos(mhwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
	}

	GetCursorPos(&curpt);

	for (int i = 0; i < 256; i++)
	{
		curkey[i] = GetAsyncKeyState(i) < 0;
		if (curkey[i] && !lastkey[i])
		{
			switch (i)
			{
			case VK_F7:
				DestroyWindow(mhwnd);
				break;
			case VK_SPACE:													//switch from transparent and opaque
			{
				long style = GetWindowLong(mhwnd, GWL_EXSTYLE);
				if (state == 2)												//to transparent
				{
					SetWindowLong(mhwnd, GWL_EXSTYLE, style | WS_EX_TRANSPARENT);
					SetLayeredWindowAttributes(mhwnd, 0, ALPHA, LWA_ALPHA);
					state = 1;
				}
				else if (state == 1)										//to opaque
				{
					SetWindowLong(mhwnd, GWL_EXSTYLE, style & ~WS_EX_TRANSPARENT);
					SetLayeredWindowAttributes(mhwnd, 0, 255, LWA_ALPHA);
					state = 2;
				}
				break;
			}
			case VK_LBUTTON:
				if (curpt.x >= leftwindow && curpt.x <= leftwindow + xwindow && curpt.y >= topwindow && curpt.y <= topwindow + ywindow)
				{
					if (state != 1)
					{
						canmove = true;
						origin.left = leftwindow;
						origin.top = topwindow;
						origin.right = curpt.x;
						origin.bottom = curpt.y;
					}
				}
				else
				{
					canmove = false;
				}
				
				break;
			}
		}

		lastkey[i] = curkey[i];
	}
	
	if (curpt.x != lastpt.x || curpt.y != lastpt.y)
	{
		if (curkey[VK_LBUTTON] && canmove && state != 1)
		{
			leftwindow = origin.left + curpt.x - origin.right;
			topwindow = origin.top + curpt.y - origin.bottom;
			//if (leftwindow >= 0 && topwindow >= 0)
			//{
				SetWindowPos(mhwnd, HWND_TOPMOST, leftwindow, topwindow, 0, 0, SWP_NOSIZE);
			//}
			
		}
	}

	// draw 
	graphics->Clear(0);
	switch (state)
	{
	case 0:											//startup interface
		graphics->FillRectangle(&PALE, leftwindow, topwindow, xwindow, ywindow);
		graphics->FillRectangle(&GRAY, leftwindow + 50, topwindow + 150, 60, 60);
		graphics->FillEllipse(&GRAY, leftwindow + 90, topwindow + 100, 60, 60);
		graphics->FillPie(&GRAY, leftwindow + 150, topwindow + 130, 100, 60, 160, 300);
		break;
	case 1:											//transparent
		graphics->DrawImage(image, leftwindow, topwindow, xwindow, ywindow);
		break;
	case 2:											//opaque
		graphics->DrawImage(image, leftwindow, topwindow, xwindow, ywindow);
		break;
	}
	
	SIZE size = { xwindow,ywindow };
	POINT pt = { leftwindow,topwindow };
	
	if (pt.x + size.cx > XSCREEN)
	{
		size.cx = XSCREEN - pt.x - 1;
	}
	if (pt.y + size.cy > YSCREEN)
	{
		size.cy = YSCREEN - pt.y - 1;
	}
	if (pt.x < 0)
	{
		size.cx += pt.x;
		pt.x = 0;
	}
	if (pt.y < 0)
	{
		size.cy += pt.y;
		pt.y = 0;
	}
	UpdateLayeredWindow(mhwnd, hdc, NULL, &size, memDC, &pt, 0, &bf, ULW_ALPHA);
}